
#ifndef __terrainH__
#define __terrainH__

#include "glsl.h"
#include "3d.h"
#include "image.h"
#include "physics.h"
#include "buf.h"


namespace WtfGraphics {
	class HeightMapShader: public WtfEngine::GLSLProgram {
		int	mHeightMapLocation;
		int	mTextureLocation;
		int mScaleLocation;

		public:
			HeightMapShader();

			void GetLocations();
			void PassOther();

			void setScale(const tVector& scale);

			DATA_OBJECT(HeightMapShader, sizeof(HeightMapShader));
	};

	class TerrainHeightMap: public GraphicsData {
	public:
		typedef enum {
			HTMAP_DEFAULT,
			/// Height map is stored as a texture (and rendered using special shader)
			HTMAP_TEXTURE,
			/// Height map is stored as an array of floats
			HTMAP_FLOATV,
			/// Height map is stored as a mesh (VBO)
			HTMAP_MESH
		} tDataType;

	private:
      HeightMapShader::tRef		mrTerrainShader;
      WtfEngine::Texture::tRef	mrHeightMap;
      WtfEngine::GLSLProgram::tRef	mrShader;
      WtfEngine::NonCopyBuffer<tScalar>::tRef	mrvfHeightMap;
      Mesh::tRef						mrMesh;

		iVector2D		mvDim;
		tVector			mvScale;
		tDataType		mDataType;
		
		public:
			TerrainHeightMap(const WtfEngine::StringPool::Entry& sName):
				GraphicsData(sName), mDataType(HTMAP_DEFAULT) {};
			~TerrainHeightMap() {
				Destroy();
			};

			/// Creates the height map from an image
			void Create(const tVector& vScale, const WtfEngine::Image::tRef& rHeightMap, tDataType = HTMAP_DEFAULT);
			/// Creates the height map from an array
			void Create(const tVector& vScale, const iVector2D& vDim, WtfEngine::NonCopyBuffer<tScalar>::tRef& rHeightMap, tDataType = HTMAP_DEFAULT);

			void Destroy();

			void render();

			void RenderFromTexture();
			void RenderFromFloatv();
			void RenderFromMesh();

			tDataType GetDefaultType();

			void setShader(const WtfEngine::GLSLProgram::tRef&	rShader) {
				mrShader = rShader;
			};

			inline const iVector2D& getDim() const {
				return mvDim;
			};
			inline const tVector& getScale() const {
				return mvScale;
			};
			inline tDataType getDataType() const {
				return mDataType;
			};

			WtfEngine::Texture::tRef getDataTexture() const {
				return mrHeightMap;
			};
			WtfEngine::NonCopyBuffer<tScalar>::tRef	getDataFloatv() const {
				return mrvfHeightMap;
			};
			Mesh::tRef getMesh() const {
				return mrMesh;
			};

			/// Gets a physical model representing the terrain
			WtfEngine::PhysicalModel::tCacheRef getPhysicalModel();

			static void Test();
			static WtfEngine::IDataObject * Load(const WtfEngine::StringPool::Entry& sPath);
			// TODO: correct size
			DATA_LOADABLE(TerrainHeightMap, sizeof(TerrainHeightMap));
	};
};

#endif
